package controllers;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import models.ManualObjective;
import models.Paciente;
import models.RegistroPeso;
import notifiers.Notificador;
import play.db.Model;
import play.exceptions.TemplateNotFoundException;
import play.mvc.With;
import controllers.securesocial.SecureSocial;

@With(SecureSocial.class)
public class ManualObjectives extends CustomCRUD {

	public static void list(int page, String search, String searchFields, String orderBy, String order) {
		try {
			Paciente paciente = (Paciente) getUsuarioLogueado();

			Long userId = paciente.id;

			ObjectType type = ObjectType.get(getControllerClass());
			notFoundIfNull(type);

			if (page < 1) {
				page = 1;
			}

			List<Model> objects = type.findPage(page, search, searchFields, orderBy, order, (String) request.args.get("where"));

			List<Model> filteredObjects = new ArrayList<Model>();

			for (Model model : objects) {
				if (((ManualObjective) model).getPaciente() != null && ((ManualObjective) model).getPaciente().id.equals(userId)) {
					filteredObjects.add(model);
				}
			}

			objects = filteredObjects;

			Long count = new Long(objects.size());
			Long totalCount = new Long(objects.size());

			try {
				render(type, objects, count, totalCount, page, orderBy, order, userId);
			} catch (TemplateNotFoundException e) {
				render(getControllerName() + "/list.html", type, objects, count, totalCount, page, orderBy, order, userId);
			}
		}
		// TODO: crear una excepción de negocio
		catch (ClassCastException e) {
			Notificador.emailObjetivoManualAsignado(session.get("nutri_nombre"), session.get("paciente_nombre"), session.get("paciente_mail"));
			redirect("/nutri");
		}
	}

	public static void newManualObjective(Long pacienteId) throws Exception {

		ObjectType type = ObjectType.get(getControllerClass());

		notFoundIfNull(type);

		ManualObjective object = new ManualObjective();
		
		object.setCumplidoObjetivoManual(false);
		Paciente paciente = getPacienteToCreateObjective(pacienteId);
		object.setPaciente(paciente);
		session.put("paciente_id", pacienteId);
		render(getControllerName() + "/newManualObjective.html", type, pacienteId, object, paciente);
	}

	public static Long useAndDestroyPacienteId() {
		
//		// pongo esto porque tira error al cargar data del YML. TODO HAY QUE SACAR AL PACIENTE DE LA SESSION!!!
//		if (session == null) {
//			return null;
//		}
		
		String pacienteIdString = session.get("paciente_id");
		if (pacienteIdString != null) {
			Long pacienteId = Long.parseLong(pacienteIdString);
			return pacienteId;
		}
		return null;
	}

	// Es para retornar el paciente en caso de que el usuario logueado sea un
	// Nutri
	public static Paciente getPacienteToCreateObjective(Long pacienteId) {
		return getUsuarioLogueado().getPacienteToCreateObjective(pacienteId);
	}

	public static void show(String id) throws Exception {

		ObjectType type = ObjectType.get(getControllerClass());
		notFoundIfNull(type);

		ManualObjective object = (ManualObjective) type.findById(id);

		notFoundIfNull(object);

		try {
			render(type, object);
		} catch (TemplateNotFoundException e) {
			render(getControllerName() + "/show.html", type, object);
		}
	}
	
	public static List<List<Double>> cargarGrafico(Long objetivoId, Date fechaInicio, Date fechaFin, Double pesoInicial, Double pesoDeseado) throws Exception {
		
		List<List<Double>> datosGrafico = new ArrayList<List<Double>>();
		
		ObjectType type = ObjectType.get(getControllerClass());
		notFoundIfNull(type);
		
		ManualObjective objetivo = (ManualObjective) type.findById(objetivoId.toString());
		
		notFoundIfNull(objetivo);
		
		List<RegistroPeso> registrosPeso = RegistroPeso.find("byPaciente", objetivo.getPaciente()).fetch();
		
		registrosPeso = filtrarRegistroPesosPorFecha(registrosPeso, fechaInicio, fechaFin);
		
		Long datoIndex = 0L;
		
		Calendar fechaGrafico = Calendar.getInstance(); // Para avanzar día a día
		fechaGrafico.setTime(fechaInicio);
		fechaGrafico.add(Calendar.DATE, -1);
		
		Iterator<RegistroPeso> registroPesoIterator = registrosPeso.iterator();
		
		RegistroPeso registroActual = registroPesoIterator.next(); // para registrar los dias
		
		// arma una cadena asi [1,45],[2,46],[3,46],[4,47],
		while(fechaGrafico.getTime().before(fechaFin)) {
			
			Boolean tieneMasPesos = registroPesoIterator.hasNext();
			
			if(registroActual.getFechaActual().before(fechaGrafico.getTime()) && tieneMasPesos) {
				registroActual = registroPesoIterator.next();
			}
			
			List<Double> registro = new ArrayList<Double>();
			
			registro.add(new Double(datoIndex));
			
			if(tieneMasPesos) {
				registro.add(registroActual.getPesoActual());
			}
			else {
				registro.add(null);
			}
			
			datosGrafico.add(registro);
			
			fechaGrafico.add(Calendar.DATE, 1);
			datoIndex++;
		}
		
		return datosGrafico;
		
	}
	
	private static List<RegistroPeso> filtrarRegistroPesosPorFecha(List<RegistroPeso> todos, Date fechaInicio, Date fechaFin) {
		
		// Agrando los rangos en 1 día para <= y >=
		Calendar inicio = Calendar.getInstance();
		inicio.setTime(fechaInicio);
		inicio.add(Calendar.DATE, -1);
		
		fechaInicio = inicio.getTime();
		
		Calendar fin = Calendar.getInstance();
		fin.setTime(fechaFin);
		fin.add(Calendar.DATE, 1);
		
		fechaFin = fin.getTime();
		
		List<RegistroPeso> filtrados = new ArrayList<RegistroPeso>();
		
		for (RegistroPeso registroPeso : todos) {
			if (registroPeso.getFechaActual().after(fechaInicio) && registroPeso.getFechaActual().before(fechaFin)) {
				filtrados.add(registroPeso);
			}
		}
		
		return filtrados;
	}
	
}
